package cn.iocoder.yudao.module.system.controller.admin.category;

import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;

import cn.iocoder.yudao.module.system.controller.admin.category.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.category.CategoryDO;
import cn.iocoder.yudao.module.system.service.category.CategoryService;

// 新增导入
import cn.iocoder.yudao.module.system.dal.mysql.category.CategoryMapper;
import cn.iocoder.yudao.module.system.dal.mysql.category.CategoryBooksMapper;
import cn.iocoder.yudao.module.system.dal.dataobject.category.CategoryBooksDO;
import cn.iocoder.yudao.module.system.dal.mysql.book.BookMapper;
import cn.iocoder.yudao.module.system.dal.dataobject.book.BookDO;
import cn.iocoder.yudao.module.system.dal.mysql.bookcollection.BookcollectionMapper;
import cn.iocoder.yudao.module.system.dal.dataobject.bookcollection.BookcollectionDO;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.collection.CollUtil;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;

@Tag(name = "管理后台 - 绘本分类")
@RestController
@RequestMapping("/huiben/category")
@Validated
@Slf4j
public class CategoryController {

    @Resource
    private CategoryService categoryService;
    
    // 新增依赖注入
    @Resource
    private CategoryMapper categoryMapper;
    
    @Resource
    private CategoryBooksMapper categoryBooksMapper;
    
    @Resource
    private BookMapper bookMapper;
    
    @Resource
    private BookcollectionMapper bookcollectionMapper;

    @PostMapping("/create")
    @Operation(summary = "创建绘本分类")
    @PreAuthorize("@ss.hasPermission('huiben:category:create')")
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Long> createCategory(@Valid @RequestBody CreateCategoryVO createReqVO) {
        try {
            log.info("开始创建绘本分类: categoryName={}, categoryType={}, relatedIds={}", 
                    createReqVO.getCategoryName(), createReqVO.getCategoryType(), createReqVO.getRelatedIds());
            
            // 1. 参数校验
            validateCreateCategoryParams(createReqVO);
            
            // 2. 插入分类主表
            Long categoryId = createCategoryRecord(createReqVO.getCategoryName(), createReqVO.getCategoryType());
            
            // 3. 确定关联类型
            String type = determineRelatedType(createReqVO.getCategoryType());
            
            // 4. 验证关联ID有效性
            validateRelatedIds(createReqVO.getRelatedIds(), type);
            
            // 5. 批量插入关联数据
            int insertCount = categoryBooksMapper.insertBatch(categoryId, createReqVO.getRelatedIds(), type);
            
            log.info("绘本分类创建成功: categoryId={}, categoryName={}, categoryType={}, relatedIds={}, insertCount={}", 
                    categoryId, createReqVO.getCategoryName(), createReqVO.getCategoryType(), createReqVO.getRelatedIds(), insertCount);
            
            return success(categoryId);
            
        } catch (Exception e) {
            log.error("绘本分类创建失败: categoryName={}, error={}", createReqVO.getCategoryName(), e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 验证创建分类参数
     */
    private void validateCreateCategoryParams(CreateCategoryVO createReqVO) {
        // 验证分类名称
        if (StrUtil.isEmpty(createReqVO.getCategoryName())) {
            throw exception(CATEGORY_NAME_EMPTY);
        }
        if (createReqVO.getCategoryName().length() < 2 || createReqVO.getCategoryName().length() > 30) {
            throw exception(CATEGORY_NAME_LENGTH_INVALID);
        }
        
        // 验证分类类型
        if (StrUtil.isEmpty(createReqVO.getCategoryType())) {
            throw exception(CATEGORY_TYPE_INVALID);
        }
        if (!Arrays.asList("zh", "en", "all").contains(createReqVO.getCategoryType())) {
            throw exception(CATEGORY_TYPE_INVALID);
        }
        
        // 验证关联ID数组
        if (CollUtil.isEmpty(createReqVO.getRelatedIds())) {
            throw exception(CATEGORY_RELATED_IDS_EMPTY);
        }
    }
    
    /**
     * 创建分类主记录
     */
    private Long createCategoryRecord(String categoryName, String categoryType) {
        CategoryDO category = new CategoryDO();
        category.setName(categoryName);
        category.setLanguage(categoryType);
        
        categoryMapper.insert(category);
        Long categoryId = category.getCategoryId();
        
        log.info("创建分类记录成功: categoryId={}, categoryName={}, categoryType={}", categoryId, categoryName, categoryType);
        return categoryId;
    }
    
    /**
     * 确定关联类型
     */
    private String determineRelatedType(String categoryType) {
        if ("zh".equals(categoryType) || "en".equals(categoryType)) {
            return "books"; // 关联绘本集
        } else if ("all".equals(categoryType)) {
            return "book"; // 关联绘本
        } else {
            throw exception(CATEGORY_TYPE_INVALID);
        }
    }
    
    /**
     * 验证关联ID有效性
     */
    private void validateRelatedIds(List<Long> relatedIds, String type) {
        if (CollUtil.isEmpty(relatedIds)) {
            throw exception(CATEGORY_RELATED_IDS_EMPTY);
        }
        
        List<Long> invalidIds = new ArrayList<>();
        for (Long relatedId : relatedIds) {
            if ("books".equals(type)) {
                // 验证绘本集是否存在
                BookcollectionDO bookcollection = bookcollectionMapper.selectById(relatedId);
                if (bookcollection == null) {
                    invalidIds.add(relatedId);
                }
            } else if ("book".equals(type)) {
                // 验证绘本是否存在
                BookDO book = bookMapper.selectById(relatedId);
                if (book == null) {
                    invalidIds.add(relatedId);
                }
            }
        }
        
        if (!invalidIds.isEmpty()) {
            if ("books".equals(type)) {
                throw exception(CATEGORY_BOOK_COLLECTION_NOT_EXISTS, invalidIds);
            } else {
                throw exception(CATEGORY_BOOK_NOT_EXISTS, invalidIds);
            }
        }
        
        log.info("验证关联ID成功: relatedIds={}, type={}", relatedIds, type);
    }

    @PutMapping("/update")
    @Operation(summary = "更新绘本分类")
    @PreAuthorize("@ss.hasPermission('huiben:category:update')")
    public CommonResult<Boolean> updateCategory(@Valid @RequestBody CategorySaveReqVO updateReqVO) {
        categoryService.updateCategory(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除绘本分类")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('huiben:category:delete')")
    public CommonResult<Boolean> deleteCategory(@RequestParam("id") Long id) {
        categoryService.deleteCategory(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得绘本分类")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('huiben:category:query')")
    public CommonResult<CategoryRespVO> getCategory(@RequestParam("id") Long id) {
        CategoryDO category = categoryService.getCategory(id);
        return success(BeanUtils.toBean(category, CategoryRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得绘本分类分页")
    @PreAuthorize("@ss.hasPermission('huiben:category:query')")
    public CommonResult<PageResult<CategoryRespVO>> getCategoryPage(@Valid CategoryPageReqVO pageReqVO) {
        PageResult<CategoryDO> pageResult = categoryService.getCategoryPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, CategoryRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出绘本分类 Excel")
    @PreAuthorize("@ss.hasPermission('huiben:category:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportCategoryExcel(@Valid CategoryPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<CategoryDO> list = categoryService.getCategoryPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "绘本分类.xls", "数据", CategoryRespVO.class,
                        BeanUtils.toBean(list, CategoryRespVO.class));
    }

}